package org.ourgrid.common.statistics.control;

import java.util.Collection;

import org.ourgrid.common.interfaces.to.LocalWorkerState;
import org.ourgrid.common.spec.worker.WorkerSpec;
import org.ourgrid.common.statistics.beans.peer.Worker;
import org.ourgrid.common.statistics.util.hibernate.HibernateUtil;
import org.ourgrid.peer.dao.LocalWorkersDAO;
import org.ourgrid.peer.dao.statistics.PeerDAO;
import org.ourgrid.peer.dao.statistics.WorkerDAO;
import org.ourgrid.peer.to.LocalWorker;

import br.edu.ufcg.lsd.commune.container.servicemanager.ServiceManager;
import br.edu.ufcg.lsd.commune.identification.ServiceID;

public class WorkerControl extends EntityControl {
	
	private static WorkerControl instance = null;
	
	public static WorkerControl getInstance() {
		if (instance == null) {
			instance = new WorkerControl();
		}
		return instance;
	}
	
	protected WorkerControl() {}
	
	public void statusChanged(ServiceID workerID, LocalWorkerState workerStatus,
			ServiceManager serviceManager) {
		
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).statusChanged(workerID, workerStatus);
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}
		
		logger.leave();

	}
	
	public void statusChanged(ServiceID workerID, LocalWorkerState workerStatus, String allocatedFor,
			ServiceManager serviceManager) {
		
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).statusChanged(workerID, workerStatus, allocatedFor);
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}
		
		logger.leave();

	}
	
	public void addLocalWorker(LocalWorker localWorker, ServiceManager serviceManager) {
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).addLocalWorker(
					localWorker, serviceManager.getContainerContext());
			
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}

		logger.leave();
	}
	
	public void addRemoteWorker(WorkerSpec workerSpec, ServiceManager serviceManager, String providerDN) {
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).addRemoteWorker(workerSpec, providerDN, 
					serviceManager.getMyDeploymentID().getContainerID().getUserAtServer());
			
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}

		logger.leave();
	}
	

	public void updateWorker(WorkerSpec workerSpec, ServiceManager serviceManager) {
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).updateWorker(workerSpec);
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}
		
		logger.leave();
	}
	
	public LocalWorker getLocalWorker(ServiceID entityID, LocalWorkersDAO workerDAO) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		LocalWorker worker = workerDAO.getLocalWorker(entityID);
		
		HibernateUtil.closeSession();

		return worker;
	}
	
	public Collection<LocalWorker> getLocalWorkers(LocalWorkerState status, ServiceManager serviceManager) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		Collection<LocalWorker> workers = serviceManager.getDAO(LocalWorkersDAO.class).getLocalWorkers(status, 
				serviceManager.getContainerContext());
		HibernateUtil.closeSession();

		return workers;
	}
	
	public boolean isNewWorker(ServiceID workerEntityID, LocalWorkersDAO workerDAO) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		boolean isNew = workerDAO.isNewWorker(workerEntityID);
		HibernateUtil.closeSession();

		return isNew;
	}
	
	public Collection<ServiceID> getLocalWorkersIDs(ServiceManager serviceManager){
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		Collection<ServiceID> ids = serviceManager.getDAO(LocalWorkersDAO.class).getLocalWorkersIDs(
				serviceManager.getContainerContext());
		HibernateUtil.closeSession();

		return ids;
	}
	
	public LocalWorker removeLocalWorker(ServiceID localWorkerID, WorkerDAO workerDAO) {
		
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		LocalWorker localWorker = null;
		try {
			localWorker = workerDAO.removeLocalWorker(localWorkerID);
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}
		
		logger.leave();
		return localWorker;
	}
	
	public void removeRemoteWorker(ServiceID remoteWorkerID, ServiceManager serviceManager) {
		
		logger.enter();
		
		HibernateUtil.beginTransaction();
		
		try {
			serviceManager.getDAO(WorkerDAO.class).removeRemoteWorker(remoteWorkerID);
			HibernateUtil.commitTransaction();
		} catch (Exception e) {
			HibernateUtil.rollbackAndCloseSession();
		}
		
		logger.leave();
		
	}
	
	public Collection<Worker> findAllActiveWorkers(ServiceManager serviceManager) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		Collection<Worker> workers = serviceManager.getDAO(WorkerDAO.class).findAllActiveWorkers(
				serviceManager.getContainerContext(), serviceManager.getDAO(PeerDAO.class));
		HibernateUtil.closeSession();

		return workers;
	}
	
	public LocalWorker getRecoveredWorker(ServiceID entityID, LocalWorkersDAO workerDAO) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		LocalWorker worker = workerDAO.getRecoveredWorker(entityID);
		HibernateUtil.closeSession();

		return worker;
	}
	
	public Worker findActiveWorker(String address, WorkerDAO workerDAO) {
		HibernateUtil.getSession();
		HibernateUtil.beginTransaction();
		
		Worker worker = workerDAO.findActiveWorker(address);
		HibernateUtil.closeSession();

		return worker;
	}

}
